package org.dioib.practice.common.exception.handler;
import org.dioib.practice.common.ApiResponse;
import org.dioib.practice.common.exception.ResourceNotFoundException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
import org.springframework.web.servlet.NoHandlerFoundException;

import java.nio.file.AccessDeniedException;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

@RestControllerAdvice
public class EnhancedExceptionHandler {


    /**
     * 自定义：没有找到数据异常
     * @param ex
     * @param request
     * @return
     */
    @ExceptionHandler(ResourceNotFoundException.class)
    public ResponseEntity<ApiResponse<?>> handleResourceNotFound(ResourceNotFoundException ex, WebRequest request) {
        Map<String, Object> details = new HashMap<>();
        details.put("resource", ex.getResourceName());
        details.put("id", ex.getResourceId());

        ApiResponse<?> response = ApiResponse.error(
                        HttpStatus.NOT_FOUND.value(),
                        "RESOURCE_NOT_FOUND",
                        ex.getMessage(),
                        details
                );
        response.setTimestamp(LocalDateTime.now());
        response.setPath(request.getDescription(false));

        return new ResponseEntity<>(response, HttpStatus.NOT_FOUND);
    }

    /**
     *  NIO ACCESS_DENIED
     * @param ex
     * @param request
     * @return
     */
    @ExceptionHandler(AccessDeniedException.class)
    public ResponseEntity<ApiResponse<?>> handleAccessDenied(AccessDeniedException ex, WebRequest request) {
        ApiResponse<?> response = ApiResponse.error(
                        HttpStatus.FORBIDDEN.value(),
                        "ACCESS_DENIED",
                        "无权访问该资源",
                        null
                );
        response.setTimestamp(LocalDateTime.now());
        response.setPath(request.getDescription(false));

        return new ResponseEntity<>(response, HttpStatus.FORBIDDEN);
    }


    /**
     * HttpRequestMethodNotSupportedException
     * @param ex
     * @param request
     * @return
     */
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public ResponseEntity<ApiResponse<?>> handleMethodNotSupported(
            HttpRequestMethodNotSupportedException ex, WebRequest request) {

        Map<String, Object> details = new HashMap<>();
        details.put("supportedMethods", ex.getSupportedHttpMethods());
        details.put("requestedMethod", ex.getMethod());

        ApiResponse<?> response = ApiResponse.error(
                        HttpStatus.METHOD_NOT_ALLOWED.value(),
                        "METHOD_NOT_ALLOWED",
                        "不支持的HTTP方法",
                        details
                );
        response.setTimestamp(LocalDateTime.now());
        response.setPath(request.getDescription(false));

        return new ResponseEntity<>(response, HttpStatus.METHOD_NOT_ALLOWED);
    }

    /**
     * 上传文件最大限制异常
     * @param ex
     * @param request
     * @return
     */
    @ExceptionHandler(MaxUploadSizeExceededException.class)
    public ResponseEntity<ApiResponse<?>> handleMaxSizeException(
            MaxUploadSizeExceededException ex, WebRequest request) {

        ApiResponse<?> response = ApiResponse.error(
                        HttpStatus.PAYLOAD_TOO_LARGE.value(),
                        "FILE_TOO_LARGE",
                        "文件大小超过限制",
                        null
                );
        response.setTimestamp(LocalDateTime.now());
        response.setPath(request.getDescription(false));

        return new ResponseEntity<>(response, HttpStatus.PAYLOAD_TOO_LARGE);
    }


    /**
     * 自定义：没有找到handler
     * @param ex
     * @param request
     * @return
     */
    @ExceptionHandler(NoHandlerFoundException.class)
    public ResponseEntity<ApiResponse<?>> handleNotFound(NoHandlerFoundException ex, WebRequest request) {
        Map<String, Object> details = new HashMap<>();
        details.put("requestedUrl", ex.getRequestURL());
        details.put("httpMethod", ex.getHttpMethod());

        ApiResponse<?> response = ApiResponse.error(
                        HttpStatus.NOT_FOUND.value(),
                        "ENDPOINT_NOT_FOUND",
                        "请求的接口不存在",
                        details
                );
        response.setTimestamp(LocalDateTime.now());
        response.setPath(request.getDescription(false));

        return new ResponseEntity<>(response, HttpStatus.NOT_FOUND);
    }

    /**
     * 系统：请求体JSON格式错误
     * @param ex
     * @param request
     * @return
     */
    @ExceptionHandler(HttpMessageNotReadableException.class)
    public ResponseEntity<ApiResponse<?>> handleMessageNotReadable(
            HttpMessageNotReadableException ex, WebRequest request) {

        ApiResponse<?> response = ApiResponse.error(
                        HttpStatus.BAD_REQUEST.value(),
                        "MALFORMED_JSON",
                        "请求体JSON格式错误",
                        null
                );
        response.setTimestamp(LocalDateTime.now());
        response.setPath(request.getDescription(false));

        return new ResponseEntity<>(response, HttpStatus.BAD_REQUEST);
    }

    // 处理所有未捕获的异常
    @ExceptionHandler(Exception.class)
    public ResponseEntity<ApiResponse<?>> handleAllExceptions(Exception ex, WebRequest request) {
        ApiResponse<?> response = ApiResponse.error(
                HttpStatus.INTERNAL_SERVER_ERROR.value(),
                "SYSTEM_ERROR",
                "系统内部错误",
                null
        );
        response.setTimestamp(LocalDateTime.now());
        response.setPath(request.getDescription(false));
        return new ResponseEntity<>(response, HttpStatus.INTERNAL_SERVER_ERROR);
    }
}
